package ua.pp.bizon.cripto.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import ua.pp.bizon.cripto.file.FileFactory;
import ua.pp.bizon.cripto.file.IFile;
import ua.pp.bizon.cripto.file.IPath;
import ua.pp.bizon.cripto.file.Path;

public class FileUtilLocalImpl extends Path implements IFile {

    public FileUtilLocalImpl(String path) {
        super(Place.LOCALLY, path);
    }

    private static Log log = LogFactory.getLog(FileUtilLocalImpl.class);

    public byte[] read() throws IOException {
        log.debug("read(from=" + this + ")");
        FileInputStream stream = new FileInputStream(getPath());
        try {
            byte[] buffer = new byte[(int) new File(getPath()).length()];
            readFully(stream, buffer);
            return buffer;
        } finally {
            stream.close();
        }
    }

    public void write(String filename, byte[] data) throws IOException {
        log.debug("write(to=" + this + ",filename=" + filename + ", data.length=" + data.length + ")");
        FileOutputStream stream = new FileOutputStream(filename == "" ? new File(getPath()) : new File(getPath(), filename));
        try {
            stream.write(data);
        } finally {
            stream.close();
        }
    }

    private static void readFully(InputStream stream, byte[] buffer) throws IOException {
        int read = stream.read(buffer);
        if (read != buffer.length) {
            for (int len = read; len < buffer.length;) {
                int r = stream.read(buffer, len, buffer.length - len);
                if (r > 0) {
                    len += r;
                }
            }
        }
    }

    public boolean exists() {
        return new File(getPath()).exists();
    }

    public boolean writable() {
        return !(exists()) && new File(getPath()).getAbsoluteFile().getParentFile().isDirectory();
    }

    public boolean isDirectory() {
        return new File(getPath()).isDirectory();
    }

    public List<IPath> ls() {
        String[] children = new File(getPath()).list();
        List<IPath> rezult = new LinkedList<IPath>();
        for (String i : children) {
            rezult.add(FileFactory.getLocalFile(getPath() + File.separatorChar + i));
        }
        return rezult;
    }

    public IPath mkdir(String lastPathName) {
        new File(getPath() + File.separator + lastPathName).mkdirs();
        return FileFactory.getLocalFile(getPath() + File.separator + lastPathName);
    }

    @Override
    public boolean delete() throws IOException {
        File file = new File(getPath());
        if (file.isDirectory()){
           FileUtils.deleteDirectory(file);
           return true;
        } else
           return file.delete();
    }
}
